package com.tutu.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * @Program: Spring_New
 * @Description:
 * @Author: JK.TuTu
 * @Create: 2022-09-15
 **/
@Aspect  //表示当前类是切面类
public class AnnotationPointcut {


    /**
     * 后置通知方法 在目标方法执行后执行  returning：自定义的变量名，表示目标方法返回值，必须和通知方法的形参名一致
     *
     * @param data 是目标方法执行后的返回值，根据返回值做切面的功能处理
     */
    @AfterReturning(value = "execution(public String com.tutu.service.impl.UserServiceImpl.search())", returning = "data")
    public void after(Object data) {
        if (data != null) {
            System.out.println("后置通知捕获返回结果:" + data);
        }
        System.out.println("---------方法执行后---------");
    }

    /**
     * 前置通知方法 在目标方法执行前执行
     *
     * @param jp
     */
    @Before("execution(public void com.tutu.service.impl.UserServiceImpl.delete(int))")
    public void before(JoinPoint jp) {
        System.out.println("业务方法的签名(定义)" + jp.getSignature());
        System.out.println("业务方法的名称" + jp.getSignature().getName());
        Object[] args = jp.getArgs();
        for (Object arg : args) {
            System.out.println("业务方法的参数" + arg);
        }
        System.out.println("---------方法执行前---------");
    }

    /**
     * 环绕通知方法 在目标方法的前后都可以执行 方法必须有一个返回值
     *
     * @param jp
     * @throws Throwable
     */
    @Around("execution(public Integer com.tutu.service.impl.UserServiceImpl.update(String))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕通知前...");
        //可根据目标方法的参数  判断是否执行目标方法
        //获取目标方法的所有参数
        Object[] args = jp.getArgs();
        String name = (String) args[0];
        if ("tom".equals(name)) {
            //执行目标方法proceed  获取目标方法的返回值
            Object proceed = jp.proceed();
            System.out.println("目标方法返回值:" + proceed);
        }
        System.out.println("环绕通知后...");
    }

    /**
     * 异常通知方法  在目标方法抛出异常后执行 注解的throwing属性用于指定所发生的异常对象 必须与方法的参数名一致
     *
     * @param exception
     */
    @AfterThrowing(value = "execution(public void com.tutu.service.impl.UserServiceImpl.add(int,int))", throwing = "exception")
    public void AfterThrowing(Exception exception) {
        System.out.println("异常通知:" + exception.getMessage());
    }

    /**
     * Poincut不是通知注解 当较多的通知方法使用的切入点表达式相同时 可以使用此注解修饰的方法名代替所编写的切入点表达式
     * 此注解的方法没有实际作用 无需在方法体内编写代码 一般用private修饰
     */
    @Pointcut("execution(* com.tutu.service.impl.UserServiceImpl.*(..))")
    private void myPointcut() {
    }

    /**
     * 最终通知注解  目标方法无论有无异常都会在目标方法执行之后执行
     */
    @After(value = "myPointcut()")
    public void after() {
        System.out.println("最终通知...");
    }


}
